package fun.lifepoem.blog.service;

import fun.lifepoem.blog.common.BaseEnum;
import fun.lifepoem.blog.domain.Article;
import fun.lifepoem.blog.domain.ArticleTag;
import fun.lifepoem.blog.domain.CommitRecord;
import fun.lifepoem.blog.domain.Tag;
import fun.lifepoem.blog.domain.bo.TagBO;
import fun.lifepoem.blog.domain.dto.gitee.GiteeFallbackBean;
import fun.lifepoem.blog.domain.dto.gitee.unit.Commits;
import fun.lifepoem.blog.domain.note.AnalysisArticleTag;
import fun.lifepoem.blog.mapper.ArticleMapper;
import fun.lifepoem.blog.mapper.ArticleTagMapper;
import fun.lifepoem.blog.mapper.CommitRecordMapper;
import fun.lifepoem.blog.mapper.TagMapper;
import fun.lifepoem.blog.utils.SnowFlakeUtils;
import fun.lifepoem.blog.utils.localfile.LocalFileUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Yiwyn
 * @create 2022/9/19 23:43
 */
@Service
@Slf4j
public class GiteeFallbackService {


    @Autowired
    private TagMapper tagMapper;

    @Autowired
    private ArticleMapper articleMapper;

    @Autowired
    private ArticleTagMapper articleTagMapper;

    @Autowired
    private LocalFileUtils localFileUtils;

    @Autowired
    private CommitRecordMapper commitRecordMapper;


    public void giteePushFallback(GiteeFallbackBean payload) throws IOException {
        List<Commits> commits = payload.getCommits();

        List<String> added = new ArrayList<>();
        List<String> modified = new ArrayList<>();
        List<String> removed = new ArrayList<>();

        //便利commit进行操作
        for (Commits commit : commits) {
            added.addAll(commit.getAdded());
            modified.addAll(commit.getModified());
            removed.addAll(commit.getRemoved());
        }

        if (!CollectionUtils.isEmpty(added)) {
//            addArticle(added);
        }
        if (!CollectionUtils.isEmpty(modified)) {
//            modifiedArticle(modified);
        }
        if (!CollectionUtils.isEmpty(removed)) {
//            removeArticle(removed);
        }
    }

    public void giteePushFallback(List<CommitRecord> commitRecords) throws IOException {

        log.info("本次任务检索的需要执行的commit:{}", commitRecords);

        Date now = new Date();

        List<String> added = new ArrayList<>();
        List<String> modified = new ArrayList<>();
        List<String> removed = new ArrayList<>();

        //便利commit进行操作
        for (CommitRecord record : commitRecords) {
            switch (record.getType()) {
                case "ADD":
                    added.add(record.getPath());
                    break;
                case "DELETE":
                    removed.add(record.getPath());
                    break;
                case "MODIFY":
                    modified.add(record.getPath());
                    break;
            }
            record.setUseFlag(true);
            record.setUseDate(now);
        }

        if (!CollectionUtils.isEmpty(added)) {
            addArticle(added);
        }
        if (!CollectionUtils.isEmpty(modified)) {
            modifiedArticle(modified);
        }
        if (!CollectionUtils.isEmpty(removed)) {
            removeArticle(removed);
        }
        List<String> ids = commitRecords.stream().filter(CommitRecord::getUseFlag).map(CommitRecord::getId).collect(Collectors.toList());

        int row = commitRecordMapper.updateBatch(ids, new CommitRecord() {{
            setUseDate(now);
            setUseFlag(true);
        }});

        log.info("本次更新文章数量:{}", row);
    }

    private void addArticle(List<String> paths) throws IOException {

        Date now = new Date();

        //遍历路径
        for (String path : paths) {
            AnalysisArticleTag articlesTag = localFileUtils.getArticlesTagFromCommmitPath(path);
            List<String> tags = articlesTag.getTags();
            File file = articlesTag.getFile();
            List<TagBO> tagBOS = tagMapper.selectTagByTagNames(tags);
            List<String> existTags = tagBOS.stream().map(TagBO::getTagName).collect(Collectors.toList());
            List<String> saveTagStrs = tags.stream().filter(p -> !existTags.contains(p)).collect(Collectors.toList());
            List<Tag> saveTags = new ArrayList<>();
            //更新tag
            if (!CollectionUtils.isEmpty(saveTagStrs)) {
                saveTags = saveTagStrs.stream().map(p -> new Tag() {{
                    setId(String.valueOf(SnowFlakeUtils.Instance().getSnowId()));
                    setTagName(p);
                    setCreateTime(now);
                    setSource(BaseEnum.ARTICLE_FROM_GIT.getCode());
                    setDelFlag(false);
                }}).collect(Collectors.toList());
                int i = tagMapper.insertBatch(saveTags);
                if (i != 0) {
                    log.info("更新tag成功:{}", saveTagStrs);
                }
            } else {
                log.info("需要更新的tag为空");
            }

            //更新文章
            if (file != null) {
                String content = localFileUtils.getContentFromFile(file);
                Article article = new Article() {{
                    setId(String.valueOf(SnowFlakeUtils.Instance().getSnowId()));
                    setArticleName(file.getName());
                    setArticleAuthor("Yiwyn");
                    setContent(content);
                    setGitUrl(path);
                    setCreateTime(now);
                    setSource(BaseEnum.ARTICLE_FROM_GIT.getCode());
                    setDelFlag(false);
                }};

                int i = articleMapper.insert(article);
                if (i != 0) {
                    log.info("更新文章成功:{}", article.getArticleName());

                    List<TagBO> collect = saveTags.stream().map(p -> new TagBO() {{
                        setId(p.getId());
                        setTagName(p.getTagName());
                    }}).collect(Collectors.toList());

                    tagBOS.addAll(collect);

                    if (!CollectionUtils.isEmpty(tagBOS)) {
                        List<ArticleTag> articleTags = tagBOS.stream().map(p -> new ArticleTag() {{
                            setId(String.valueOf(SnowFlakeUtils.Instance().getSnowId()));
                            setArticleId(article.getId());
                            setTagId(p.getId());
                            setCreateTime(now);
                            setDelFlag(false);
                        }}).collect(Collectors.toList());

                        int i1 = articleTagMapper.insertBatch(articleTags);
                        log.info("更新文章标签关系:{}", i1);
                    }

                }
            }
        }

    }

    private void modifiedArticle(List<String> paths) throws IOException {
        for (String path : paths) {
            AnalysisArticleTag articlesTag = localFileUtils.getArticlesTagFromCommmitPath(path);
            File file = articlesTag.getFile();
            String content = localFileUtils.getContentFromFile(file);
            //更新修改的内容，通过tag和file决定
            Article article = articleMapper.selectByPath(path);
            if (article == null) {
                log.info("本次提交修改的文章不存在:{}", path);
                return;
            }
            article.setContent(content);
            article.setUpdateTime(new Date());

            int i = articleMapper.updateByPrimaryKey(article);

            log.info("本次提交修改的文章结果，影响行数:{}", i);

        }
    }

    private void removeArticle(List<String> paths) {
        for (String path : paths) {
            AnalysisArticleTag articlesTag = localFileUtils.getArticlesTagFromCommmitPath(path);
            File file = articlesTag.getFile();
            //删除文件，先删除数据库文件再删除原始文件
            Article article = articleMapper.selectByPath(path);
            if (article != null) {
                int i = articleMapper.deleteByPrimaryKey(article.getId());
                log.info("删除文章:{},影响行数:{}", path, i);

                int i1 = articleTagMapper.deleteByArticleIds(article.getId());
                log.info("删除文章标签,影响行数:{}", i1);
            }
            if (file != null) {
                //删除文件
                file.delete();
            }
        }
    }
}
